package org.ehe.finance.voucher.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.ehe.common.core.BaseController;
import org.ehe.common.core.domain.R;
import org.ehe.common.log.annotation.Log;
import org.ehe.common.log.enums.BusinessType;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.finance.voucher.domain.bo.*;
import org.ehe.finance.voucher.domain.vo.ErpFinanceVoucherDetailVo;
import org.ehe.finance.voucher.mapper.ErpFinanceVoucherDetailMapper.VoucherDetailSummary;
import org.ehe.finance.voucher.mapper.ErpFinanceVoucherDetailMapper.VoucherTotalAmount;
import org.ehe.finance.voucher.service.ErpFinanceVoucherDetailService;
import org.ehe.finance.voucher.service.ErpFinanceVoucherDetailService.ValidateResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
 * 记账凭证明细管理控制器
 * @author :zhangnn
 * @className :ErpFinanceVoucherDetailController
 * @description: TODO
 * @date 2025-08-25 15:16:19
 */
@RestController
@RequestMapping("/finance/voucher-detail")
@RequiredArgsConstructor
@Validated
public class ErpFinanceVoucherDetailController extends BaseController {

    private final ErpFinanceVoucherDetailService voucherDetailService;

    /**
     * 分页查询凭证明细
     * @param bo
     * @param pageQuery
     * @return
     */
    @GetMapping("/page")
    @SaCheckPermission("finance:voucherDetail:list")
    public TableDataInfo<ErpFinanceVoucherDetailVo> page(@Valid VoucherDetailQueryBo bo, PageQuery pageQuery) {
        return voucherDetailService.pageVoucherDetails(bo, pageQuery);
    }

    /**
     * 获取凭证明细详情
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @SaCheckPermission("finance:voucherDetail:query")
    public R<ErpFinanceVoucherDetailVo> getById(@PathVariable @NotNull Long id) {
        ErpFinanceVoucherDetailVo result = voucherDetailService.getVoucherDetailById(id);
        return R.ok(result);
    }

    /**
     * 创建凭证明细
     * @param createBo
     * @return
     */
    @Log(title = "创建凭证明细", linkType = "finance", businessType = BusinessType.INSERT, idField = "id", nameField = "voucherId")
    @PostMapping
    @SaCheckPermission("finance:voucherDetail:add")
    public R<Long> create(@Valid @RequestBody VoucherDetailCreateBo createBo) {
        Long id = voucherDetailService.createVoucherDetail(createBo);
        return R.ok("创建成功", id);
    }

    /**
     * 更新凭证明细
     * @param updateBo
     * @return
     */
    @Log(title = "更新凭证明细", linkType = "finance", businessType = BusinessType.UPDATE, idField = "id", nameField = "voucherId")
    @PostMapping("/edit")
    @SaCheckPermission("finance:voucherDetail:edit")
    public R<Void> update(@Valid @RequestBody VoucherDetailUpdateBo updateBo) {
        voucherDetailService.updateVoucherDetail(updateBo);
        return R.ok("更新成功");
    }

    /**
     * 删除凭证明细
     * @param id
     * @return
     */
    @Log(title = "删除凭证明细", linkType = "finance", businessType = BusinessType.DELETE, idField = "id", nameField = "voucherId")
    @DeleteMapping("/{id}")
    @SaCheckPermission("finance:voucherDetail:remove")
    public R<Void> delete(@PathVariable @NotNull Long id) {
        voucherDetailService.deleteVoucherDetail(id);
        return R.ok("删除成功");
    }

    /**
     * 批量删除凭证明细
     * @param ids
     * @return
     */
    @Log(title = "删除凭证明细", linkType = "finance", businessType = BusinessType.DELETE, idField = "id", nameField = "voucherId")
    @DeleteMapping("/batch")
    @SaCheckPermission("finance:voucherDetail:remove")
    public R<Void> batchDelete(@RequestBody @NotNull List<Long> ids) {
        voucherDetailService.batchDeleteVoucherDetails(ids);
        return R.ok("删除成功");
    }

    /**
     * 根据凭证ID获取明细列表
     * @param voucherId
     * @return
     */
    @GetMapping("/voucher/{voucherId}")
    @SaCheckPermission("finance:voucherDetail:list")
    public R<List<ErpFinanceVoucherDetailVo>> getDetailsByVoucherId(@PathVariable @NotNull Long voucherId) {
        List<ErpFinanceVoucherDetailVo> result = voucherDetailService.getDetailsByVoucherId(voucherId);
        return R.ok(result);
    }

    /**
     * 批量获取凭证明细
     * @param voucherIds
     * @return
     */
    @PostMapping("/batch-vouchers")
    @SaCheckPermission("finance:voucherDetail:list")
    public R<List<ErpFinanceVoucherDetailVo>> getDetailsByVoucherIds(@RequestBody @NotNull List<Long> voucherIds) {
        List<ErpFinanceVoucherDetailVo> result = voucherDetailService.getDetailsByVoucherIds(voucherIds);
        return R.ok(result);
    }

    /**
     * 批量保存凭证明细
     * @param batchSaveBo
     * @return
     */
    @Log(title = "批量保存凭证明细", linkType = "finance", businessType = BusinessType.INSERT, idField = "id", nameField = "voucherId")
    @PostMapping("/batch-save")
    @SaCheckPermission("finance:voucherDetail:edit")
    public R<Void> batchSave(@Valid @RequestBody VoucherDetailBatchSaveBo batchSaveBo) {
        voucherDetailService.batchSaveVoucherDetails(batchSaveBo);
        return R.ok("保存成功");
    }

    /**
     * 获取凭证借贷合计
     * @param voucherId
     * @return
     */
    @GetMapping("/total-amount/{voucherId}")
    @SaCheckPermission("finance:voucherDetail:query")
    public R<VoucherTotalAmount> getVoucherTotalAmount(@PathVariable @NotNull Long voucherId) {
        VoucherTotalAmount result = voucherDetailService.getVoucherTotalAmount(voucherId);
        return R.ok(result);
    }

    /**
     * 验证凭证借贷平衡
     * @param voucherId
     * @return
     */
    @GetMapping("/validate-balance/{voucherId}")
    @SaCheckPermission("finance:voucherDetail:query")
    public R<Boolean> validateBalance(@PathVariable @NotNull Long voucherId) {
        boolean balanced = voucherDetailService.validateVoucherBalance(voucherId);
        return R.ok(balanced);
    }

    /**
     * 获取下一个分录号
     * @param voucherId
     * @return
     */
    @GetMapping("/next-entry-no/{voucherId}")
    @SaCheckPermission("finance:voucherDetail:add")
    public R<Integer> getNextEntryNo(@PathVariable @NotNull Long voucherId) {
        Integer nextEntryNo = voucherDetailService.getNextEntryNo(voucherId);
        return R.ok(nextEntryNo);
    }

    /**
     * 根据科目查询明细
     * @param subjectId
     * @param startDate
     * @param endDate
     * @return
     */
    @GetMapping("/subject/{subjectId}")
    @SaCheckPermission("finance:voucherDetail:list")
    public R<List<ErpFinanceVoucherDetailVo>> getDetailsBySubject(@PathVariable @NotNull Long subjectId,
                                                                  @RequestParam(required = false) LocalDate startDate,
                                                                  @RequestParam(required = false) LocalDate endDate) {
        List<ErpFinanceVoucherDetailVo> result = voucherDetailService.getDetailsBySubject(subjectId, startDate, endDate);
        return R.ok(result);
    }

    /**
     * 根据辅助核算查询明细
     * @param customerId
     * @param supplierId
     * @param employeeId
     * @param projectId
     * @param departmentId
     * @param startDate
     * @param endDate
     * @return
     */
    @GetMapping("/auxiliary")
    @SaCheckPermission("finance:voucherDetail:list")
    public R<List<ErpFinanceVoucherDetailVo>> getDetailsByAuxiliary(@RequestParam(required = false) Long customerId,
                                                                    @RequestParam(required = false) Long supplierId,
                                                                    @RequestParam(required = false) Long employeeId,
                                                                    @RequestParam(required = false) Long projectId,
                                                                    @RequestParam(required = false) Long departmentId,
                                                                    @RequestParam(required = false) LocalDate startDate,
                                                                    @RequestParam(required = false) LocalDate endDate) {
        List<ErpFinanceVoucherDetailVo> result = voucherDetailService.getDetailsByAuxiliary(
            customerId, supplierId, employeeId, projectId, departmentId, startDate, endDate);
        return R.ok(result);
    }

    /**
     * 统计科目发生额
     * @param subjectIds
     * @param startDate
     * @param endDate
     * @return
     */
    @PostMapping("/subject-stat")
    @SaCheckPermission("finance:voucherDetail:list")
    public R<List<VoucherDetailStatBo>> getSubjectAmountStat(@RequestBody @NotNull List<Long> subjectIds,
                                                             @RequestParam(required = false) LocalDate startDate,
                                                             @RequestParam(required = false) LocalDate endDate) {
        List<VoucherDetailStatBo> result = voucherDetailService.getSubjectAmountStat(subjectIds, startDate, endDate);
        return R.ok(result);
    }

    /**
     * 获取凭证明细汇总
     * @param voucherId
     * @return
     */
    @GetMapping("/summary/{voucherId}")
    @SaCheckPermission("finance:voucherDetail:query")
    public R<List<VoucherDetailSummary>> getVoucherDetailSummary(@PathVariable @NotNull Long voucherId) {
        List<VoucherDetailSummary> result = voucherDetailService.getVoucherDetailSummary(voucherId);
        return R.ok(result);
    }

    /**
     * 获取科目余额
     * @param subjectId
     * @param endDate
     * @return
     */
    @GetMapping("/subject-balance/{subjectId}")
    @SaCheckPermission("finance:voucherDetail:query")
    public R<BigDecimal> getSubjectBalance(@PathVariable @NotNull Long subjectId,
                                           @RequestParam(required = false) LocalDate endDate) {
        BigDecimal balance = voucherDetailService.getSubjectBalance(subjectId, endDate);
        return R.ok(balance);
    }

    /**
     * 复制凭证明细
     * @param sourceVoucherId
     * @param targetVoucherId
     * @return
     */
    @PostMapping("/copy/{sourceVoucherId}/{targetVoucherId}")
    @SaCheckPermission("finance:voucherDetail:add")
    public R<Void> copyVoucherDetails(@PathVariable @NotNull Long sourceVoucherId,
                                      @PathVariable @NotNull Long targetVoucherId) {
        voucherDetailService.copyVoucherDetails(sourceVoucherId, targetVoucherId);
        return R.ok("复制成功");
    }

    /**
     * 重新排序分录号
     * @param voucherId
     * @return
     */
    @PostMapping("/reorder/{voucherId}")
    @SaCheckPermission("finance:voucherDetail:edit")
    public R<Void> reorderEntryNos(@PathVariable @NotNull Long voucherId) {
        voucherDetailService.reorderEntryNos(voucherId);
        return R.ok("排序成功");
    }

    /**
     * 查询多币种明细
     * @param voucherId
     * @return
     */
    @GetMapping("/multi-currency/{voucherId}")
    @SaCheckPermission("finance:voucherDetail:list")
    public R<List<ErpFinanceVoucherDetailVo>> getMultiCurrencyDetails(@PathVariable @NotNull Long voucherId) {
        List<ErpFinanceVoucherDetailVo> result = voucherDetailService.getMultiCurrencyDetails(voucherId);
        return R.ok(result);
    }

    /**
     * 验证明细数据
     * @param details
     * @return
     */
    @PostMapping("/validate")
    @SaCheckPermission("finance:voucherDetail:query")
    public R<ValidateResult> validateDetails(@RequestBody @NotNull List<VoucherDetailCreateBo> details) {
        ValidateResult result = voucherDetailService.validateDetails(details);
        return R.ok(result);
    }

    /**
     * 计算外币金额
     * @param amount
     * @param exchangeRate
     * @return
     */
    @GetMapping("/calculate-foreign-amount")
    @SaCheckPermission("finance:voucherDetail:query")
    public R<BigDecimal> calculateForeignAmount(@RequestParam BigDecimal amount,
                                                @RequestParam BigDecimal exchangeRate) {
        BigDecimal foreignAmount = voucherDetailService.calculateForeignAmount(amount, exchangeRate);
        return R.ok(foreignAmount);
    }

    /**
     * 导出凭证明细
     * @param bo
     * @return
     */
    @Log(title = "导出凭证明细", linkType = "finance", businessType = BusinessType.EXPORT, idField = "id", nameField = "voucherId")
    @PostMapping("/export")
    @SaCheckPermission("finance:voucherDetail:export")
    public R<List<ErpFinanceVoucherDetailVo>> export(@Valid @RequestBody VoucherDetailQueryBo bo) {
        List<ErpFinanceVoucherDetailVo> result = voucherDetailService.exportVoucherDetails(bo);
        return R.ok(result);
    }

    /**
     * 删除凭证的所有明细
     * @param voucherId
     * @return
     */
    @Log(title = "删除凭证的所有明细", linkType = "finance", businessType = BusinessType.DELETE, idField = "id", nameField = "voucherId")
    @DeleteMapping("/voucher/{voucherId}")
    @SaCheckPermission("finance:voucherDetail:remove")
    public R<Void> deleteDetailsByVoucherId(@PathVariable @NotNull Long voucherId) {
        voucherDetailService.deleteDetailsByVoucherId(voucherId);
        return R.ok("删除成功");
    }
}
